1. Constructors and Inheritance in Solidity

Question:
Write a contract Parent that initializes a public state variable owner to the deployer’s address using a constructor. Then, write a contract Child that inherits from Parent and adds a constructor that accepts an integer age as a parameter and stores it in a public variable age.

Answer:

// Parent Contract
pragma solidity ^0.8.0;

contract Parent {
    address public owner;

    constructor() {
        owner = msg.sender;
    }
}

// Child Contract
contract Child is Parent {
    uint public age;

    constructor(uint _age) {
        age = _age;
    }
}

2. Interacting Between Contracts in Solidity

Question:
Write two contracts, Caller and Callee. In Callee, write a public function multiply(uint x, uint y) that returns the product of x and y. In Caller, write a function callMultiply that calls multiply from Callee and returns the result.

Answer:

// Callee Contract
pragma solidity ^0.8.0;

contract Callee {
    function multiply(uint x, uint y) public pure returns (uint) {
        return x * y;
    }
}

// Caller Contract
contract Caller {
    function callMultiply(address calleeAddress, uint x, uint y) public view returns (uint) {
        Callee callee = Callee(calleeAddress);
        return callee.multiply(x, y);
    }
}

3. Errors, Checks, and Conditions in Solidity

Question:
Write a function withdraw(uint amount) inside a contract Bank that allows the caller to withdraw ether only if their balance is greater than or equal to amount. If not, it should revert the transaction with a custom error message “Insufficient balance”.

Answer:

pragma solidity ^0.8.0;

contract Bank {
    mapping(address => uint) public balances;

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw(uint amount) public {
        require(balances[msg.sender] >= amount, "Insufficient balance");
        balances[msg.sender] -= amount;
        payable(msg.sender).transfer(amount);
    }
}

4. Enums, Access Control, and Function Updates in Solidity

Question:
Write a contract Voting where an enum State has values Created, Voting, and Ended. Implement a modifier onlyOwner that restricts access to the contract owner, and use it in the function startVoting which transitions the state from Created to Voting.

Answer:

pragma solidity ^0.8.0;

contract Voting {
    address public owner;
    enum State { Created, Voting, Ended }
    State public state;

    constructor() {
        owner = msg.sender;
        state = State.Created;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Not the contract owner");
        _;
    }

    function startVoting() public onlyOwner {
        require(state == State.Created, "Invalid state");
        state = State.Voting;
    }
}

5. Events in Solidity: Emitting Logs

Question:
Write a contract Token that allows users to transfer tokens. Emit an event Transfer with parameters from, to, and amount whenever a transfer occurs.

Answer:

pragma solidity ^0.8.0;

contract Token {
    mapping(address => uint) public balances;

    event Transfer(address indexed from, address indexed to, uint amount);

    constructor(uint initialSupply) {
        balances[msg.sender] = initialSupply;
    }

    function transfer(address to, uint amount) public {
        require(balances[msg.sender] >= amount, "Insufficient balance");
        balances[msg.sender] -= amount;
        balances[to] += amount;
        emit Transfer(msg.sender, to, amount);
    }
}

6. Functions in Solidity: Types and Use Cases

Question:
Write a contract Calculator with two public functions: add(uint a, uint b) and subtract(int a, int b). The add function should return the sum, and the subtract function should return the difference.

Answer:

pragma solidity ^0.8.0;

contract Calculator {
    function add(uint a, uint b) public pure returns (uint) {
        return a + b;
    }

    function subtract(int a, int b) public pure returns (int) {
        return a - b;
    }
}

7. Inheritance in Solidity with Function Overrides

Question:
Write a contract Animal with a virtual function makeSound that returns "Animal sound". Then, create a contract Dog that overrides makeSound and returns "Bark!".

Answer:

pragma solidity ^0.8.0;

contract Animal {
    function makeSound() public virtual pure returns (string memory) {
        return "Animal sound";
    }
}

contract Dog is Animal {
    function makeSound() public override pure returns (string memory) {
        return "Bark!";
    }
}

8. Access Control: Using onlyOwner Modifier

Question:
Write a contract Store where only the owner can set the price of a product using the setPrice(uint _price) function. Use the onlyOwner modifier to restrict access.

Answer:

pragma solidity ^0.8.0;

contract Store {
    address public owner;
    uint public price;

    constructor() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Not the contract owner");
        _;
    }

    function setPrice(uint _price) public onlyOwner {
        price = _price;
    }
}

9. Reentrancy Guard Example

Question:
Write a contract SafeBank where users can deposit and withdraw Ether. Implement a reentrancy guard on the withdraw function to prevent reentrancy attacks.

Answer:

pragma solidity ^0.8.0;

contract SafeBank {
    mapping(address => uint) public balances;
    bool internal locked;

    modifier noReentrancy() {
        require(!locked, "ReentrancyGuard: reentrant call");
        locked = true;
        _;
        locked = false;
    }

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw(uint amount) public noReentrancy {
        require(balances[msg.sender] >= amount, "Insufficient balance");
        balances[msg.sender] -= amount;
        payable(msg.sender).transfer(amount);
    }
}

10. Using Events for Logging Function Calls

Question:
Write a contract Counter that has a public function increment which increases a counter by 1. Emit an event Incremented every time the function is called with the new counter value.

Answer:

pragma solidity ^0.8.0;

contract Counter {
    uint public count;

    event Incremented(uint newCount);

    function increment() public {
        count += 1;
        emit Incremented(count);
    }
}